﻿using System;
using System.Collections.Specialized;
using System.IO;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Compiler;
using System.Xml.Linq;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
using Microsoft.SharePoint.WorkflowActions;

namespace AdlibWorkflowActivity
{
    public class insertUpdate : Activity
    {
        public static readonly DependencyProperty AddressProperty = 
            DependencyProperty.Register("Address", typeof(string), typeof(insertUpdate));

        public static readonly DependencyProperty DatabaseProperty =
            DependencyProperty.Register("Database", typeof(string), typeof(insertUpdate));

        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.Register("Command", typeof(string), typeof(insertUpdate));

        public static readonly DependencyProperty XmlDataProperty =
            DependencyProperty.Register("XmlData", typeof(string), typeof(insertUpdate));

        public static readonly DependencyProperty PrirefProperty =
            DependencyProperty.Register("Priref", typeof(string), typeof(insertUpdate));
    
        [ValidationOption(ValidationOption.Required)]
        public string Address
        {
            get { return (string)GetValue(AddressProperty); }
            set { SetValue(AddressProperty, value); }
        }
        [ValidationOption(ValidationOption.Required)]
        public string Database
        {
            get { return (string)GetValue(DatabaseProperty); }
            set { SetValue(DatabaseProperty, value); }
        }
        [ValidationOption(ValidationOption.Required)]
        public string Command
        {
            get { return (string)GetValue(CommandProperty); }
            set { SetValue(CommandProperty, value); }
        }
        [ValidationOption(ValidationOption.Required)]
        public string XmlData
        {
            get { return (string)GetValue(XmlDataProperty); }
            set { SetValue(XmlDataProperty, value); }
        }
        [ValidationOption(ValidationOption.Optional)]
        public string Priref
        {
            get { return (string)GetValue(PrirefProperty); }
            set { SetValue(PrirefProperty, value); }
        }

        protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
        {
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                byte[] response;
                try
                {
                    using (WebClient client = new WebClient())
                    {
                        response = client.UploadValues(Address, new NameValueCollection 
                        {
                            {"database", Database},
                            {"xmltype", "grouped"},
                            {"command", Command},
                            {"data", Regex.Replace(SPEncode.HtmlEncode(XmlData), @"[^\x20-\x7F]", string.Empty)}
                        });
                    }
                }
                catch (Exception ex)
                {
                    response = new byte[0];
                    ((ISharePointService)executionContext.GetService(typeof(ISharePointService))).LogToHistoryList(base.WorkflowInstanceId, SPWorkflowHistoryEventType.WorkflowComment, 0, TimeSpan.MinValue, string.Empty, string.Format("Webclient encountered an error: {0}", ex.Message), string.Empty);
                }
                if (response.Length != 0)
                {
                    using (MemoryStream stream = new MemoryStream(response, false))
                    {
                        StreamReader reader = new StreamReader(stream, true);
                        XDocument xmldoc = XDocument.Load(reader, LoadOptions.None);
                        string priref = string.Empty;
                        string adlibError = string.Empty;
                        priref = (from node in xmldoc.Descendants("priref") select node.Value).FirstOrDefault();
                        adlibError = (from node in xmldoc.Descendants("message") select node.Value).FirstOrDefault();
                        this.Priref = priref;
                        if (String.IsNullOrEmpty(priref))
                        {
                            if (!String.IsNullOrEmpty(adlibError))
                            {
                                ((ISharePointService)executionContext.GetService(typeof(ISharePointService))).LogToHistoryList(base.WorkflowInstanceId, SPWorkflowHistoryEventType.WorkflowComment, 0, TimeSpan.MinValue, string.Empty, string.Format("Adlib API returned an error: {0}", adlibError), string.Empty);
                            }
                        }
                    }
                }
            });
            return ActivityExecutionStatus.Closed;
        }
        protected override ActivityExecutionStatus HandleFault(ActivityExecutionContext executionContext, Exception exception)
        {
            ((ISharePointService) executionContext.GetService(typeof(ISharePointService))).LogToHistoryList(base.WorkflowInstanceId, SPWorkflowHistoryEventType.WorkflowComment, 0, TimeSpan.MinValue, string.Empty, string.Format("WorkFlow encountered an error: {0}", exception.Message), string.Empty);
            return ActivityExecutionStatus.Closed;
        }
    }
}
